package org.jeecg.modules.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.SsoUtil;
import org.jeecg.common.util.YouBianCodeUtil;
import org.jeecg.enums.common.DataScopeEnum;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysScope;
import org.jeecg.modules.system.entity.SysScopeDepart;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.mapper.SysDepartMapper;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.jeecg.modules.system.model.SysDepartTreeModel;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.ISysScopeService;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.service.ISysScopeDepartService;
import org.jeecg.modules.system.util.FindsDepartsChildrenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.embedded.netty.SslServerCustomizer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * 部门表 服务实现类
 * <p>
 * 
 * @Author Steve
 * @Since 2019-01-22
 */
@Service
public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart> implements ISysDepartService {

	@Autowired
	private SysDepartMapper sysDepartMapper;
	@Autowired
	private SysUserMapper sysUserMapper;
	@Autowired
	private ISysUserService sysUserService;
	@Autowired
	private ISysScopeService sysScopeService;
	@Autowired
	private ISysScopeDepartService sysScopeDepartService;

	/**
	 * queryTreeList 对应 queryTreeList 查询所有的部门数据,以树结构形式响应给前端
	 */
	@Override
	public List<SysDepartTreeModel> queryTreeList() {
		LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
		query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
		query.orderByAsc(SysDepart::getDepartOrder);
		List<SysDepart> list = this.list(query);
		// 调用wrapTreeDataToTreeList方法生成树状数据
		List<SysDepartTreeModel> listResult = FindsDepartsChildrenUtil.wrapTreeDataToTreeList(list);
		return listResult;
	}

	/**
	 * 根据部门获取所属管理处
	 * @param departId
	 * @return
	 */
	@Override
	public SysDepart getOfficeByDepartId(String departId) {
		if(StringUtils.isEmpty(departId)){
			return null;
		}
		SysDepart depart = sysDepartMapper.get(departId);
		if(null == depart){
			return null;
		}
		if(CommonConstant.DEPART_PROPERTY_OFFICE.equals(depart.getDepartProperty())){
			return depart;
		}
		SysDepart office = depart.getParentDepart();
		while(office != null){
			if(CommonConstant.DEPART_PROPERTY_OFFICE.equals(office.getDepartProperty())){
				return office;
			}else {
				office = sysDepartMapper.get(office.getId()).getParentDepart();
			}
		}
		return depart;
	}

	/**
	 * queryCompanyTreeList 对应 queryCompanyTreeList 查询所有的部门中属性为公司的数据,以树结构形式响应给前端
	 */
	@Override
	public List<SysDepartTreeModel> queryCompanyTreeList() {
		LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
		query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
		query.eq(SysDepart::getDepartProperty, CommonConstant.DEPART_PROPERTY_COMPANY);
		query.or();
		query.eq(SysDepart::getDepartProperty, CommonConstant.DEPART_PROPERTY_OFFICE);
		query.orderByAsc(SysDepart::getDepartOrder);
		List<SysDepart> list = this.list(query);
		// 调用wrapTreeDataToTreeList方法生成树状数据
		List<SysDepartTreeModel> listResult = FindsDepartsChildrenUtil.wrapTreeDataToTreeList(list);
		return listResult;
	}


	/**
	 * saveDepartData 对应 add 保存用户在页面添加的新的部门对象数据
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveDepartData(SysDepart sysDepart) {
		sysDepart.setId(String.valueOf(IdWorker.getId()));
		// 先判断该对象有无父级ID,有则意味着不是最高级,否则意味着是最高级
		// 获取父级ID
		String parentId = sysDepart.getParentId();
		String[] codeArray = generateOrgCode(parentId);
		sysDepart.setOrgCode(codeArray[0]);
		String orgType = codeArray[1];
		sysDepart.setOrgType(String.valueOf(orgType));
		sysDepart.setCreateTime(new Date());
		sysDepart.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
		this.save(sysDepart);

		//默认给【系统管理员】添加该部门
		SysScope sysScope = sysScopeService.getByScopeType(DataScopeEnum.DATA_SCOPE_TENANT_ADMIN.getCode());
		if (sysScope != null){
			SysScopeDepart sysScopeDepart = new SysScopeDepart();
			sysScopeDepart.setScopeId(sysScope.getId());
			sysScopeDepart.setDepartId(sysDepart.getId());
			sysScopeDepart.setHalfStatus(1);
			sysScopeDepartService.save(sysScopeDepart);
		}
	}
	
	/**
	 * saveDepartData 的调用方法,生成部门编码和部门类型
	 * 
	 * @param parentId
	 * @return
	 */
	private String[] generateOrgCode(String parentId) {	
		//update-begin--Author:Steve  Date:20190201 for：组织机构添加数据代码调整
				LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
				LambdaQueryWrapper<SysDepart> query1 = new LambdaQueryWrapper<SysDepart>();
				String[] strArray = new String[2];
		        // 创建一个List集合,存储查询返回的所有SysDepart对象
		        List<SysDepart> departList = new ArrayList<>();
				// 定义新编码字符串
				String newOrgCode = "";
				// 定义旧编码字符串
				String oldOrgCode = "";
				// 定义部门类型
				String orgType = "";		
				// 如果是最高级,则查询出同级的org_code, 调用工具类生成编码并返回                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
				if (StringUtil.isNullOrEmpty(parentId)) {
					// 线判断数据库中的表是否为空,空则直接返回初始编码
					query1.eq(SysDepart::getParentId, "");
					query1.orderByDesc(SysDepart::getOrgCode);
					departList = this.list(query1);
					if(departList == null || departList.size() == 0) {
						strArray[0] = YouBianCodeUtil.getNextYouBianCode(null);
						strArray[1] = "1";
						return strArray;
					}else {
					SysDepart depart = departList.get(0);
					oldOrgCode = depart.getOrgCode();
					orgType = depart.getOrgType();
					newOrgCode = YouBianCodeUtil.getNextYouBianCode(oldOrgCode);
					}
				} else { // 反之则查询出所有同级的部门,获取结果后有两种情况,有同级和没有同级
					// 封装查询同级的条件
					query.eq(SysDepart::getParentId, parentId);
					// 降序排序
					query.orderByDesc(SysDepart::getOrgCode);
					// 查询出同级部门的集合
					List<SysDepart> parentList = this.list(query);
					// 查询出父级部门
					SysDepart depart = this.getById(parentId);
					// 获取父级部门的Code
					String parentCode = depart.getOrgCode();
					// 根据父级部门类型算出当前部门的类型
					orgType = String.valueOf(Integer.valueOf(depart.getOrgType()) + 1);
					// 处理同级部门为null的情况
					if (parentList == null || parentList.size() == 0) {
						// 直接生成当前的部门编码并返回
						newOrgCode = YouBianCodeUtil.getSubYouBianCode(parentCode, null);
					} else { //处理有同级部门的情况
						// 获取同级部门的编码,利用工具类
						String subCode = parentList.get(0).getOrgCode();
						// 返回生成的当前部门编码
						newOrgCode = YouBianCodeUtil.getSubYouBianCode(parentCode, subCode);
					}
				}
				// 返回最终封装了部门编码和部门类型的数组
				strArray[0] = newOrgCode;
				strArray[1] = orgType;
				return strArray;
		//update-end--Author:Steve  Date:20190201 for：组织机构添加数据代码调整
	} 

	
	/**
	 * updateDepartDataById 对应 edit 根据部门主键来更新对应的部门数据
	 */
	@Override
	@Transactional
	public Result updateDepartDataById(SysDepart oldSysDepart, SysDepart newSysDepart) {
		if (!oldSysDepart.getDepartProperty().equals(newSysDepart.getDepartProperty())){ //更改机构属性 -只有该机构下没有人员才可修改
			//是否有人员属于该公司
			List<SysUser> sysUserList = sysUserMapper.findChildUserByDepartId(oldSysDepart.getId());
			if (sysUserList.size() > 0) return Result.error("当前机构下存在用户,属性不可修改为公司,请先删除或移走该机构下的用户！");
		}
		SysDepart newParent = sysDepartMapper.get(newSysDepart.getParentId());
		if (newParent == null){
			return Result.error("所选的上级部门,在系统中不存在！");
		}
		newSysDepart.setParentIds(newParent.getParentIds() + newParent.getId() + ",");
		this.updateById(newSysDepart);
		if (!CommonConstant.DEPART_PROPERTY_COMPANY.equals(oldSysDepart.getDepartProperty())){ //管理处/部门 - 需修改其下用户的所属公司
			String newCompanyId = null;
			if (CommonConstant.DEPART_PROPERTY_COMPANY.equals(newParent.getDepartProperty())){
				newCompanyId = newParent.getId();
			} else {
				String[] parentIdArr = newParent.getParentIds().split(",");
				for (int i=parentIdArr.length - 1; i>=0;i--){
					newParent = sysDepartMapper.get(parentIdArr[i]);
					if (CommonConstant.DEPART_PROPERTY_COMPANY.equals(newParent.getDepartProperty())){
						newCompanyId = newParent.getId();
						break;
					}
				}
			}
			if (StringUtils.isBlank(newCompanyId)) return Result.error("新公司不存在！");
			List<SysUser> sysUserList = sysUserMapper.findChildUserByDepartId(oldSysDepart.getId());
			for (SysUser sysUser:sysUserList){
				sysUser.setCompanyId(newCompanyId);
			}
			if (sysUserList.size() > 0){
				sysUserService.updateBatchById(sysUserList);
			}
		}
		//更新子部门
		List<SysDepart> childDepartList = sysDepartMapper.findChildsByParentIds(oldSysDepart.getParentIds());
		for (SysDepart childDepart:childDepartList){
			childDepart.setParentIds(childDepart.getParentIds().replace(oldSysDepart.getParentIds(),newSysDepart.getParentIds()));
//			childDepart.setParentIds(childDepart.getParentIds().replace(",",";"));
//			childDepart.setMemo(childDepart.getMemo() == null? "父类部门变动":childDepart.getMemo() + "|父类部门变动");
		}
		if (childDepartList.size() > 0){
			sysDepartMapper.updateBatchById(childDepartList);
		}
		return Result.ok("处理成功");
	}


	/**
	 * <p>
	 * 根据关键字搜索相关的部门数据
	 * </p>
	 */
	@Override
	public List<SysDepartTreeModel> searhBy(String keyWord) {
		LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
		query.like(SysDepart::getDepartName, keyWord);
		//update-begin--Author:huangzhilin  Date:20140417 for：[bugfree号]组织机构搜索回显优化--------------------
		SysDepartTreeModel model = new SysDepartTreeModel();
		List<SysDepart> departList = this.list(query);
		List<SysDepartTreeModel> newList = new ArrayList<>();
		if(departList.size() > 0) {
			for(SysDepart depart : departList) {
				model = new SysDepartTreeModel(depart);
				model.setChildren(null);
	    //update-end--Author:huangzhilin  Date:20140417 for：[bugfree号]组织机构搜索功回显优化----------------------
				newList.add(model);
			}
			return newList;
		}
		return null;
	}


	/**
	 * <p>
	 * 根据关键字搜索相关的部门数据
	 * </p>
	 */
	@Override
	public List<SysDepartTreeModel> searhCompanyBy(String keyWord) {
		LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
		query.like(SysDepart::getDepartName, keyWord);
		query.eq(SysDepart::getDelFlag, 0);
		query.eq(SysDepart::getDepartProperty, CommonConstant.DEPART_PROPERTY_COMPANY);
		//update-begin--Author:huangzhilin  Date:20140417 for：[bugfree号]组织机构搜索回显优化--------------------
		SysDepartTreeModel model = new SysDepartTreeModel();
		List<SysDepart> departList = this.list(query);
		List<SysDepartTreeModel> newList = new ArrayList<>();
		if(departList.size() > 0) {
			for(SysDepart depart : departList) {
				model = new SysDepartTreeModel(depart);
				model.setChildren(null);
				//update-end--Author:huangzhilin  Date:20140417 for：[bugfree号]组织机构搜索功回显优化----------------------
				newList.add(model);
			}
			return newList;
		}
		return null;
	}

	/**
	 * 根据部门id删除并且删除其可能存在的子级任何部门
	 */
	@Override
	public boolean delete(String id) {
		List<String> idList = new ArrayList<>();
		idList.add(id);
		this.checkChildrenExists(id, idList);
		boolean ok = this.removeByIds(idList);
		return ok;
	}
	
	/**
	 * delete 方法调用
	 * @param id
	 * @param idList
	 */
	private void checkChildrenExists(String id, List<String> idList) {	
		LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
		query.eq(SysDepart::getParentId,id);
		List<SysDepart> departList = this.list(query);
		if(departList != null && departList.size() > 0) {
			for(SysDepart depart : departList) {
				idList.add(depart.getId());
				this.checkChildrenExists(depart.getId(), idList);
			}
		}
	}

	@Override
	public List<SysDepart> queryUserDeparts(String userId) {
		return baseMapper.queryUserDeparts(userId);
	}

	/**
	 * 查询id是否为管理处
	 *
	 * @param id
	 * @return
	 */
	@Override
	public Integer selectMange(String id) {
		return sysDepartMapper.selectMange(id);
	}

	/**
	 * 用户树查询
	 *
	 * @return
	 */
	@Override
	public List<SysDepartTreeModel> queryUserTreeList() {
		LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<>();
		query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
		query.eq(SysDepart::getDepartProperty,CommonConstant.DEPART_PROPERTY_COMPANY);
		query.orderByAsc(SysDepart::getDepartOrder);
		List<SysDepart> list = sysDepartMapper.queryUserTreeList();
		// 调用wrapTreeDataToTreeList方法生成树状数据
		List<SysDepartTreeModel> listResult = FindsDepartsChildrenUtil.wrapTreeDataToTreeList(list);
		return listResult;
	}

	/**
	 * 部门树查询
	 *
	 * @return
	 */
	@Override
	public List<SysDepartTreeModel> queryDepartTreeList() {
		LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<>();
		query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
		query.eq(SysDepart::getDepartProperty,CommonConstant.DEPART_PROPERTY_COMPANY);
		query.orderByAsc(SysDepart::getDepartOrder);
		List<SysDepart> list = sysDepartMapper.queryDepartTreeList();
		// 调用wrapTreeDataToTreeList方法生成树状数据
		List<SysDepartTreeModel> listResult = FindsDepartsChildrenUtil.wrapTreeDataToTreeList(list);
		return listResult;
	}

	@Override
	public List<SysDepart> findAll(){
		return sysDepartMapper.findAll();
	}

	@Override
	public String selectParentId(String id) {
		return sysDepartMapper.selectParentId(id);
	}

	@Override
	public String selectOfficeByProjectId(String id) {
		return sysDepartMapper.selectOfficeByProjectId(id);
	}

	@Override
	public SysDepart getCompanyByDepartId(String departId) {
		if(StringUtils.isEmpty(departId)) return null;
		SysDepart depart = sysDepartMapper.get(departId);
		if(null == depart) return null;
		if(CommonConstant.DEPART_PROPERTY_COMPANY.equals(depart.getDepartProperty())) return depart;
		SysDepart company = depart.getParentDepart();
		while(company != null){
			if(CommonConstant.DEPART_PROPERTY_COMPANY.equals(company.getDepartProperty())){
				return company;
			}
			company = sysDepartMapper.get(company.getId()).getParentDepart();
		}
		return depart;

	}

	@Override
	public List<String> queryDepartPositionList(String departId) {
		return sysDepartMapper.queryDepartPositionList(departId);
	}

	@Override
	public SysDepart queryDepartId(String userId) {
		return sysDepartMapper.queryDepartId(userId);
	}

	@Override
	public List<SysDepart> findChildByParentIdAndName(String parentId,String departId, String departName) {
		return sysDepartMapper.findChildByParentIdAndName(parentId,departId,departName);
	}

	@Override
	public SysDepart getDepartName(String projectId) {
		return sysDepartMapper.getDepartName(projectId);
	}

	@Override
	public List<SysDepart> queryServerTreeList(String tenantId) {
		return sysDepartMapper.queryServerTreeList(tenantId);
	}

	@Override
	public void serverSave(SysDepart sysDepart) {
		if (StringUtils.isBlank(sysDepart.getId())){
			sysDepart.setId(String.valueOf(IdWorker.getId()));
		}
		sysDepart.setCreateBy(SsoUtil.getLoginUser().getId());
		sysDepart.setCreateTime(new Date());
		sysDepart.setUpdateBy(SsoUtil.getLoginUser().getId());
		sysDepart.setUpdateTime(new Date());
		sysDepart.setDelFlag("0");
		sysDepartMapper.serverSave(sysDepart);
	}

	@Override
	public List<SysDepart> querySubTreeByParentId(SysDepart sysDepart) {
		return sysDepartMapper.querySubTreeByParentId(sysDepart);
	}

	@Override
	public SysDepart getServerById(String tenantId, String id) {
		return sysDepartMapper.getServerById(tenantId,id);
	}

	@Override
	public int serverCountChild(String tenantId, String parentId, String departName) {
		return sysDepartMapper.serverCountChild(tenantId,parentId,departName);
	}

	@Override
	public void serverUpdateName(String id, String name) {
		sysDepartMapper.serverUpdateName(id,name);
	}

	/**
	 * Oa部门树查询
	 *
	 * @return
	 */
	@Override
	public List<SysDepartTreeModel> queryDepartTreeListOa() {
		LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<>();
		query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
		query.eq(SysDepart::getDepartProperty,CommonConstant.DEPART_PROPERTY_COMPANY);
		query.orderByAsc(SysDepart::getDepartOrder);
		List<SysDepart> list = sysDepartMapper.queryDepartTreeListOa();
		// 调用wrapTreeDataToTreeList方法生成树状数据
		List<SysDepartTreeModel> listResult = FindsDepartsChildrenUtil.wrapTreeDataToTreeList(list,"floor");
		return listResult;
	}
}
